package com.amumu.drama.common.modules.fuioupay.utils;


import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;


public class RsaUtil {

	private static final String KEY_ALGORITHM = "RSA";
	private static final String ALGORITHM_MD5RSA = "MD5WithRSA";
	
	static {
		try {
			java.security.Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 私钥签名
	 */
	public static String sign2Base64ByMd5Rsa(String base64PriRsa, String inputStr,String charset) {
		return sign2Base64ByAlg(base64PriRsa, inputStr, ALGORITHM_MD5RSA,charset);
	}
	
	/**
	 * 公钥验签
	 */
	public static boolean verifySignByMd5Rsa(String base64PubRsa, String src, String base64SignValue,String charset) {
		return verifySignByAlg(base64PubRsa, src, base64SignValue, ALGORITHM_MD5RSA,charset);
	}
	
	/**
	 * 公钥加密
	 */
	public static String encryptByRsaPub(String src, String base64PubRsa,String charset) {
		try {
			PublicKey publicKey = genPublicKey(base64PubRsa);
			byte[] encryptBytes = encryptByKey(src.getBytes(charset), publicKey);
			return Base64.encodeBase64String(encryptBytes);
		} catch (Exception e) {
			e.printStackTrace();
			throw new IllegalArgumentException("rsa加密失败");
		}
	}
	
	/**
	 * 私钥解密
	 */
	public static String decryptByRsaPri(String base64Src, String base64PriRsa,String charset) {
		try {
			PrivateKey privateKey = genPrivateKey(base64PriRsa);
			return new String(decryptKey(Base64.decodeBase64(base64Src), privateKey), charset);
		} catch (Exception e) {
			e.printStackTrace();
			throw new IllegalArgumentException("rsa解密失败");
		}
	}

	private static String sign2Base64ByAlg(String base64PriRsa, String inputStr, String algorithm,String charset) {
		try {
			PrivateKey privateKey = genPrivateKey(base64PriRsa);
			Signature signature = Signature.getInstance(algorithm, "BC");
			signature.initSign(privateKey);
			signature.update(inputStr.getBytes(charset));
			return Base64.encodeBase64String(signature.sign());
		} catch (Exception e) {
			e.printStackTrace();
			throw new IllegalArgumentException("rsa签名异常");
		}
	}
	
	private static boolean verifySignByAlg(String base64PubRsa, String src, String base64SignValue, String algorithm,String charset) {
		try {
			PublicKey publicKey = genPublicKey(base64PubRsa);
			Signature signature = Signature.getInstance(algorithm, "BC");
			signature.initVerify(publicKey);
			signature.update(src.getBytes(charset));
			return signature.verify(Base64.decodeBase64(base64SignValue));
		} catch (Exception e) {
			e.printStackTrace();
			throw new IllegalArgumentException("rsa验证签名异常");
		}
	}

	private static PrivateKey genPrivateKey(String base64Rsa) {
		try {
			KeyFactory kf = KeyFactory.getInstance(KEY_ALGORITHM, "BC");
			PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(base64Rsa));
			return kf.generatePrivate(keySpec);
		} catch (Exception e) {
			e.printStackTrace();
			throw new IllegalArgumentException("初始化秘钥异常");
		}
	}

	private static PublicKey genPublicKey(String base64Rsa) {
		try {
			KeyFactory kf = KeyFactory.getInstance(KEY_ALGORITHM, "BC");
			X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decodeBase64(base64Rsa));
			return kf.generatePublic(keySpec);
		} catch (Exception e) {
			e.printStackTrace();
			throw new IllegalArgumentException("初始化秘钥失败");
		}
	}
	
	public static String convertPubRsaFile2Str(String fileStr){
		PublicKey pk = genPublicKey(fileStr);
		return Base64.encodeBase64String(pk.getEncoded());
	}
	
	public static String convertPriRsaFile2Str(String fileStr){
		PrivateKey pk = genPrivateKey(fileStr);
		return Base64.encodeBase64String(pk.getEncoded());
	}
	/**
	 * 公钥加密
	 */
	private static byte[] encryptByKey(byte[] srcData, Key publicKey) {
		try {
			Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
			cipher.init(Cipher.ENCRYPT_MODE, publicKey);
			// 分段加密
			int blockSize = cipher.getOutputSize(srcData.length) - 11;
			byte[] encryptedData = null;
			for (int i = 0; i < srcData.length; i += blockSize) {
				// 注意要使用2的倍数，否则会出现加密后的内容再解密时为乱码
				byte[] doFinal = cipher.doFinal(subarray(srcData, i, i + blockSize));
				encryptedData = addAll(encryptedData, doFinal);
			}
			return encryptedData;

		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	private static byte[] decryptKey(byte[] srcData, Key key) {
		try {
			Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
			cipher.init(Cipher.DECRYPT_MODE, key);
			// 分段加密
			int blockSize = cipher.getOutputSize(srcData.length);
			byte[] decryptData = null;

			for (int i = 0; i < srcData.length; i += blockSize) {
				byte[] doFinal = cipher.doFinal(subarray(srcData, i, i + blockSize));

				decryptData = addAll(decryptData, doFinal);
			}
			return decryptData;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	private static byte[] subarray(byte[] array, int startIndexInclusive, int endIndexExclusive) {
		if (array == null) {
			return null;
		}
		if (startIndexInclusive < 0) {
			startIndexInclusive = 0;
		}
		if (endIndexExclusive > array.length) {
			endIndexExclusive = array.length;
		}
		int newSize = endIndexExclusive - startIndexInclusive;

		if (newSize <= 0) {
			return new byte[0];
		}

		byte[] subarray = new byte[newSize];

		System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);

		return subarray;
	}

	private static byte[] addAll(byte[] array1, byte[] array2) {
		if (array1 == null) {
			return clone(array2);
		} else if (array2 == null) {
			return clone(array1);
		}
		byte[] joinedArray = new byte[array1.length + array2.length];
		System.arraycopy(array1, 0, joinedArray, 0, array1.length);
		System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
		return joinedArray;
	}

	public static byte[] clone(byte[] array) {
		if (array == null) {
			return null;
		}
		return (byte[]) array.clone();
	}
	
	public static void main(String[] args) {
		
		String pri_key = "jHkNC7ZYPubsBQKOA7KJgaOExVwIle5eQI7LCYYDsmhquM51/OJh1qfXn/EDKEXVEJ8EYXjSVkjK2zCBgzMxwnObvf/+RytUyH04+Ujem9PeGV2F/iLiSzrMvjhIdeyzHojKg7J1BKuajiUHykEJgAP23cc0TlqpMOfJZwgCfy8bLa+6mmX9ih3gJAGddfn+8uBpHBy2+OCcxeqkInuhAeSfhX0DVexMcmVI9ypsoNawKrQ7iO9uAKCps9tNZhggnl3LrS9l+d3CeQ6ulRJe+n2LhJBQSKiZYuVp4rqSWfq4zUaVX8fStdiDZyMdPasGp5o6eNWcxOWynJJWoi/VMJJb4/hpVeiwKd8V8pxdgjt8HJqwfVukE+ugPXCS08d+LiNiXyWhTzlcb9kmAzReiP/mM7kmG0Z8Jellv9A8G5koI4nC8XxQehpfKgU2O9SKdJeXUd3gflW3FeJL6e9pN1pqehnumO+/XdFT8ToIu8vO1Y0Yr5r3m3jF2FFK7AB95vAQS5ePZZDvkrOAsRvSYjrH2QAQUq/gyxxvLvAYnWqT/hsNhO+hJM7o15gsZAgGsYavhbaLzq+V0acad7WaUysncFdOm24/bBrtYRWqHYZJNx0naCLZq+QWRD85glw4+/x/bm4QNWsJiGienSpc/8zH609GNvpuFUPMq5yqhksDpr6QBD1N/vEl7DlbteLX23c53HbhVUbXFSVu0pcRATJX8cY2pNYtlvSe4b0jYRbfZE3aULzXmcRaLwsH1oEJDGm6V4B1OqBg+X2L9G3gCld8GlO83UPe3Sntj8hnN2GQw+qAgicNvokjM+Zd06P2Xur8wbkfe8HDX+QHzcQKTKoSU+UiNJGxsu2wpbFw4HnLIJGxoOAH+kuiRDNWAoK3VmASyaOhpkCUnAvijvy4lhyCGHOJPjBaYHkPdzo2crjjqRkvfeM3oJldRGWUR6QlfBZYnqSaSfz+pW8tErb3bK6dpAvRGNb3EedqQF1oIpP7piH9vC4h8oLTNrGYDxE4I4768DHm258HbuXA1/DeX0UMeTcLWrKnFunFfmizysf85t1Mvr6cgqwMF7RCSYEd4cnsn2j6JwmMp4DrPoW3O3PncOocgawmgTL5ejGHhVX1NBiPM/Dq3enTYA6YNsQU";
		String pub_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0nyklIZLDHkDvEZPKXsmrv1U3nLGCW9iOsFZQAldI5hn4LzoIyO9KXC+xDKI7khfArn2Yc1T1V45nj37bTbho/i2ED2Wme/PAIRgOm+ErfV67GU6Cl7rhDUGyNYvgihIgjuLMkaKFWankPa8RO0XO3E3yuYIxIOOanQY1f5eO2KX3aXecV1Y4A2J3OOJ3h2YJGgp9ttXE8oA3HNkhx7tm0UrjmzH3X/523cru+U4v/eM+03AfNhQyq4rr3/AWupHA2H9fZ7FkgJjGjTb+9VUHov5xhqIlEaBiD8JIUnkyoGGDZsboCjiZjV6DLwClkaK90MzdTRvfxZ5ehVLm4T1mwIDAQAB";
		String message = "123";
		String b = encryptByRsaPub(message, pub_key, "GBK");
		System.out.println(b );
	}
	
	
}
